/****************************************************************************/
/*                                                                          */
/*   FILE:    trans.c	                                                    */
/*   DATE:    13/06/97                                                      */
/*   PURPOSE: DVB-CI Transport layer - entry point into TRANS task          */
/*			- Initialization Module				    					    */
/*			- Main Module					    							*/
/*		    - Ending Module												    */
/*   TAB STOPS : 4															*/
/*   HISTORY:				                                    			*/
/*   Version	Date	  	    Written by	     Notes	    	   			*/
/*	 1.0	    13/06/1997      SCM              Initial implementation 	*/
/*	 1.03		19/09/1997		SCM         	 Windows 95 sample data		*/
/*					GL_TabSlot and GL_NbSlot management						*/
/*	 1.03			TRPT_Disconnect() : extracted slot management			*/
/*   1.05       28/12/1998      SCM              In function TRPT_Init()    */
/*        changed "if (ITC_Init(TRANS) < 0)" to "if (ITC_Init(TRANS) <= 0)" */
/*                                                                    	    */
/*--------------------------------------------------------------------------*/
/*   GENERAL COMMENTS                                                 	    */
/*									    									*/
/****************************************************************************/
#include <memory.h>
#include <stdio.h>
#include "sm_trace.h"
#include "trans.h"
#include "itc.h"			/* Inter-Task Communication */


/*--------------------------------------------------------------------------*/
/* Global Variables		                                            		*/
/*--------------------------------------------------------------------------*/
trpt_t		g_trn_tab_tcid[MAXTCID];   /* tcid table   								*/
trn_fifo_t	g_trn_tab_fifo[MAXTCID];	/* FIFO table									*/

/*--------------------------------------------------------------------------*/
/* Local Variables		                                            		*/
/*--------------------------------------------------------------------------*/
static short			s_tcCount;		/* number of established transport connections  */

/* ======================================================================== */
/* NAME : transport							    							*/
/* 									    									*/
/* DESCRIPTION : entry point into TRANS task :				    			*/
/*		 - Initialization Module				   							*/
/*		 - Main Module						    							*/
/*		 - Ending Module				         							*/
/*	The Main Module is an infinite loop :								    */
/*		 - wait events (messages from LINK task or SESS task,   			*/
/*		   internal timeouts)					    						*/
/*		 - read the first received event  			   						*/
/*		 - call the Transport State Diagram TRPT_State	          			*/
/*	                                                                  		*/
/* 									 										*/
/* INPUT PARAMETERS :							    						*/
/*									    									*/
/* OUTPUT PARAMETERS :							  							*/
/*									   										*/
/* RETURN CODE								   								*/
/*	 0    	 	success														*/
/*  -1			error														*/
/*									   										*/
/* ======================================================================== */
int transport(void* param)
{
	int		rc = 0;
	xmsg_t	xmsg;

	SM_TRACE_CRITICAL(TRMOD_TRANS, "transport() - entry\r\n");

	/* Call the Initialization Module */
	if (! TRPT_Init())
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "transport() - trpt init failed\r\n");
		rc = -1;		/* error while Initialization */
	}

	while(rc == 0)		// infinite loop
	{
		SM_TRACE_INFO(TRMOD_TRANS, "transport() - wait event infinite...\r\n");
		if (!ITC_RecvXmsg(&xmsg, ITC_INFINITE)) //Blocking Wait for event
		{
			SM_TRACE_ERROR(TRMOD_TRANS, "transport() - Error in return code\r\n");
			rc = -1;
			break;
		}

		if (xmsg.m_type == XMG_EXIT)
		{
			SM_TRACE_CRITICAL(TRMOD_TRANS, "transport() - receive XMG_EXIT\r\n");
			break;
		}

		if (xmsg.m_type)
		{
			SM_TRACE_INFO(TRMOD_TRANS, "transport() - received xmsg\r\n");
			TRPT_State(&xmsg); //Call the Transport State Diagram
		}
		else
		{
			SM_TRACE_ERROR(TRMOD_TRANS, "transport() - Error in received event\r\n");
			rc = -1;
			break;
		}
	}

	/* Call the Ending Module : should never get executed */
	TRPT_End();

	SM_TRACE_CRITICAL(TRMOD_TRANS, "transport() - return, rc=%d\r\n", rc);
	return rc;
}
/* End of Main Module */
/* ================== */


/* ======================================================================== */
/* NAME : TRPT_Init							    							*/
/* 									    									*/
/* DESCRIPTION : Initialization Module					    				*/
/*		 Transport variables initialization			    					*/
/*		 Transport State Diagram initialization 	            			*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*	1   	 	successful initialization			   						*/
/*  0			error while initialization			    					*/
/*									   										*/
/* ======================================================================== */
int TRPT_Init(void)
{
	int i;

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Init() - entry\r\n");

	s_tcCount = 0;

	if (ITC_Init(TRANS) <= 0)
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Init() - ITC init failed\r\n");
		return 0;
	}

	for (i=0; i < MAXTCID; i++)
		g_trn_tab_tcid[i].m_state = TRN_NOT_USED;

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Init() - return 1\r\n");
	return 1;
}
/* End of Initialization Module */
/* ============================ */


/* ======================================================================== */
/* NAME : TRPT_End							    							*/
/* 									    									*/
/* DESCRIPTION : Ending Module							    				*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*									   										*/
/* ======================================================================== */
void TRPT_End(void)
{
	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_End() - entry\r\n");

	ITC_End();

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_End() - return\r\n");
	return;
}
/* End of Initialization Module */
/* ============================ */


/* ======================================================================== */
/* NAME : TRPT_State													    */
/* 									    									*/
/* DESCRIPTION : Entry point of the Transport State Diagram Module			*/
/*		Read the event					       							    */
/*		Find the current TCID and the matching state diagram trnTcidIndex 			*/
/*		Call the current transition matches the received event	   			*/
/* 									   										*/
/* INPUT PARAMETERS :							   							*/
/*	s_trn_xmsg_type provides the received event 		   			*/
/*	g_trn_tab_tcid[i].m_state gives the current state of the State Diagram  		*/
/*	for the current TCID (trnTcidIndex i)					    					*/
/*									   										*/
/* OUTPUT PARAMETERS :							    						*/
/*	g_trn_tab_tcid[i].m_state is updated					    					*/
/*									  										*/
/* RETURN CODE :							  							    */
/*									 									    */
/* ======================================================================== */
void TRPT_State(xmsg_t* pXmsg)
{
	int				iRet;

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_State() - entry,pXmsg=0x%08X\r\n", pXmsg);

	iRet = 0;
	SM_TRACE_INFO(TRMOD_TRANS, "TRPT_State() - received %s(0x%02X)\r\n",
					XMSG_NAME(pXmsg->m_type), pXmsg->m_type);
	switch (pXmsg->m_type)
	{
	case TPDU :			/* Link <--> Transport */
		iRet = TRPT_Tpdu(pXmsg);
	   	break;

	case SPDU :			/* Transport <--> Session */
		iRet = TRPT_Spdu(pXmsg);
	   	break;

	case TP_CONNECT :   /* Link ---> Transport */
		iRet = TRPT_Connect(pXmsg);
		break;

	case TP_DISCONNECT :/* Link ---> Transport */
		iRet = TRPT_Disconnect(pXmsg);
		break;

	case SS_DELETE_TC :	/* Transport <--- Session */
		iRet = TRPT_Delete(pXmsg);
	   	break;

	case TP_TMPEND:
		ITC_KillTimer(pXmsg->m_bd.m_timer.m_timerId);
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_State() - timeout for a transport protocol request, timerid=0x%02X\r\n", pXmsg->m_bd.m_timer.m_timerId);
		iRet = TRPT_Timeout(pXmsg);
		break;

	case TP_TMPOLL:
		ITC_KillTimer(pXmsg->m_bd.m_timer.m_timerId);
		SM_TRACE_INFO(TRMOD_TRANS, "TRPT_State() - ending period of the polling function for transport protocol, timerid=0x%02X\r\n", pXmsg->m_bd.m_timer.m_timerId);
		iRet = TRPT_TmPoll(pXmsg);
		break;

	default :			/* unknown message */
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_State() - Unknown message is ignored\r\n");
		break;
	}

	FreeXmsg(pXmsg);

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_State() - return\r\n");
	return;
}
/* End of Transport State Diagram */
/* ============================== */




/* ======================================================================== */
/* NAME : TRPT_Connect						    							*/
/* 									    									*/
/* DESCRIPTION : Transport State Diagram : TP_CONNECT transition received 	*/
/*		- Create a new state diagram										*/
/*		- Call the action													*/
/*		- Update the state diagram											*/
/*									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_tran_conn contains the TP_CONNECT message received from LINK Task */
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*		g_trn_tab_tcid[] updated												*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int TRPT_Connect(xmsg_t* pXmsg)
{
	int trnTcidIndex;	/* trnTcidIndex of g_trn_tab_tcid[] for this new transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Connect() - entry,pXmsg=0x%08X\r\n",pXmsg);

	/* Add a new instance of the Transport State Diagram for the new transport connection 			*/
	trnTcidIndex = TRPT_AllocTcidIndex();		/* get the new instance for the transport state diagram 		*/
	if (trnTcidIndex < 0)
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Connect() - alloc trnTcidIndex failed\r\n");
		return 1;					/* can't get new instance, the request is ignored 				*/
	}

	/* Initialize new transport state diagram */
	g_trn_tab_tcid[trnTcidIndex].m_slotId = pXmsg->m_bd.m_tran_conn.m_slotId;
	SM_TRACE_INFO(TRMOD_TRANS, "TRPT_Connect() - alloc success, slotId=%d,trnTcidIndex=%d\r\n",
					g_trn_tab_tcid[trnTcidIndex].m_slotId, trnTcidIndex);

	/* Call the transport state diagram */
	if (!TRPT_Action(trnTcidIndex, pXmsg))
	{
		SM_TRACE_INFO(TRMOD_TRANS, "TRPT_Connect() - action failed, free trnTcidIndex=%d\r\n",trnTcidIndex);
		TRPT_FreeTcidIndex(trnTcidIndex);		/* error : free the new instance */
	}

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Connect() - return\r\n");
	return 0;
}


/* ======================================================================== */
/* NAME : TRPT_Disconnect						    						*/
/* 									    									*/
/* DESCRIPTION : Transport State diagram : TP_DISCONNECT received 			*/
/*	- Find all connections match with the disconnected module				*/
/*	- For each transport connection	:										*/
/*		call the action														*/
/*		free the state diagram												*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_tran_disconn contains the TP_DISCONNECT message received from LINK  */
/*		Task 																*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*			(not used in this function)										*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int TRPT_Disconnect(xmsg_t* pXmsg)
{
	int trnTcidIndex;	/* trnTcidIndex of g_trn_tab_tcid[] for the current transport connection  	*/
	int slotId;				/* extracted slot									*/

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Disconnect() - entry,pXmsg=0x%08X\r\n", pXmsg);

	slotId = pXmsg->m_bd.m_tran_disconn.m_slotId;
	/* repeat for all transport connections */
	for (trnTcidIndex=0; trnTcidIndex < MAXTCID; trnTcidIndex++)
	{
		if ((g_trn_tab_tcid[trnTcidIndex].m_state != TRN_NOT_USED) && (g_trn_tab_tcid[trnTcidIndex].m_slotId == slotId))
		{
			SM_TRACE_INFO(TRMOD_TRANS, "TRPT_Disconnect() - disconnect, trnTcidIndex=%d, slotId=%d\r\n",
						trnTcidIndex, slotId);
			if (TRPT_Action(trnTcidIndex, pXmsg))
				TRPT_FreeTcidIndex(trnTcidIndex);/* free the instance of state diagram */
		}
	}

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Disconnect() - return\r\n");
	return 0;
}


/* ======================================================================== */
/* NAME : TRPT_Tpdu								    						*/
/* 									    									*/
/* DESCRIPTION : Transport State diagram : TPDU received 					*/
/*		- Decod the TPDU													*/
/*		- Find the transport connection										*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_tpdu contains the TPDU message received from LINK   			*/
/*		Task 																*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int TRPT_Tpdu(xmsg_t* pXmsg)
{
	unsigned char*	pbTpdu;		/* pointer to TPDU									*/
	unsigned long	tpduLen;	/* length of TPDU pointed by pbTpdu					*/
	unsigned long	oneTpduLen;
	unsigned char	tpduTag;		/* TPDU type 										*/
	unsigned char	tcid;		/* Transport connection								*/
	int				tpduCount;              /* number of decoded tpdu (max 2 : tpdu + t_sb)		*/
	unsigned char*	ptr;		/* pointer to TPDU end								*/
	int				trnTcidIndex;	/* trnTcidIndex of g_trn_tab_tcid[] for the current transport connection  	*/


	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Tpdu() - entry,pXmsg=0x%08X\r\n", pXmsg);

	tpduCount = 0;
	pbTpdu = pXmsg->m_bd.m_tpdu.m_pbTpdu;
	tpduLen = pXmsg->m_bd.m_tpdu.m_len;
	//tcid  = pXmsg->m_bd.m_tpdu.m_tcid;
	//tcid = pbTpdu[2]; //pmy
	ptr    = NULL;

	/* Decod the TPDU */
	do
	{
		oneTpduLen = TRPT_XmsgDecode(pXmsg, &tpduTag, &tcid, NULL);
		if (!oneTpduLen || !tpduTag)
		{
			SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Tpdu() - Decode Error while decoding a TPDU\r\n");
			return 0;
		}

		SM_TRACE_BYTES(TRMOD_TRANS, TRLEV_NOTIFY, pXmsg->m_bd.m_tpdu.m_pbTpdu,
						oneTpduLen>1024? 1024:oneTpduLen, "TRPT_Tpdu() - recv data:");

		/* Find the transport connection */
		trnTcidIndex = TRPT_GetTcidIndex(tcid);
		if (trnTcidIndex < 0)
		{

		}

		if (trnTcidIndex < 0 || trnTcidIndex >= MAXTCID)
		{	/* not found : the event is ignored */
			/* Send IHM_WARNING to IHM Task 	*/
			SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Tpdu() - Unknown tcid %d\r\n", tcid);

			return 0;			/* free memory  */
		}
		SM_TRACE_INFO(TRMOD_TRANS, "TRPT_Tpdu() - tcid = %d found, trnTcidIndex=%d\r\n", tcid, trnTcidIndex);

		tpduCount++;	 		/* one decoded tpdu */
		pbTpdu += oneTpduLen;		/* skip to the next tpdu to decode */
		tpduLen -= oneTpduLen;

		if (tpduLen > 0)		/* maybe tpdu + t_sb */
		{
			/* Optmization : keep the end of TPDU in local memory to re-use in TRPT_Action() */
			/* ===========																		   */
			ptr = ITC_DynAlloc((unsigned short)tpduLen);	/* length = tpduLen */
			if (ptr == NULL)
			{
				SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Tpdu() - can't allocate buffer for save TPDU end\r\n");
				/* Send IHM_WARNING to IHM Task 	*/
				return 0;	/* Error */
			}
			memcpy(ptr, pbTpdu, tpduLen);
			pbTpdu = ptr;
		}

		/* Call the transport state diagram */
		pXmsg->m_bd.m_tpdu.m_len = oneTpduLen; // tpdu, add by pmy
		if (!TRPT_Action(trnTcidIndex, pXmsg))
		{
			SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Tpdu() - action failed\r\n");
			return 0;		/* free memory  */
		}

		if (tpduLen > 0) //t_sb, add by pmy
		{
			if(pXmsg->m_bd.m_tpdu.m_pbTpdu)
				ITC_DynFree(pXmsg->m_bd.m_tpdu.m_pbTpdu);
			pXmsg->m_bd.m_tpdu.m_pbTpdu = pbTpdu;
			pXmsg->m_bd.m_tpdu.m_len = tpduLen;
		}

	} while ((tpduCount < 2) && (tpduLen > 0)); /* maybe tpdu + t_sb */

	FreeXmsg(pXmsg);

    if (tpduLen != 0)
    {
    	SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Tpdu() - Error while decoding tpdu : bad length, restlen=%d\r\n", tpduLen);

		/* Send IHM_WARNING to IHM Task */
    }

	/* Release the state diagram instance if the transport connection doesn't exist */
	if (g_trn_tab_tcid[trnTcidIndex].m_state == TRN_IDLE)
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Tpdu() - stat is idle, free trnTcidIndex=%d\r\n", trnTcidIndex);
		TRPT_FreeTcidIndex(trnTcidIndex);
	}

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Tpdu() - return\r\n");
	return 0;
}



/* ======================================================================== */
/* NAME : TRPT_Spdu								    						*/
/* 									    									*/
/* DESCRIPTION : Transport State diagram : SPDU received 					*/
/*		- Find the transport connection										*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_spdu contains the SPDU message received from SESS Task		*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int TRPT_Spdu(xmsg_t* pXmsg)
{
	int trnTcidIndex;	/* trnTcidIndex of g_trn_tab_tcid[] for the current transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Spdu() - entry\r\n");

	/* Find the transport connection */
	trnTcidIndex = TRPT_GetTcidIndex(pXmsg->m_bd.m_spdu.m_tcid);
	if (trnTcidIndex < 0)
	{
		/* not found : the event is ignored */

		/* Send IHM_WARNING to IHM Task */
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Spdu() - Unknown tcid %d\r\n", pXmsg->m_bd.m_spdu.m_tcid);
	}
	else
	{
		/* Call the transport state diagram */
		SM_TRACE_INFO(TRMOD_TRANS, "TRPT_Spdu() - %s(0x%02X)\r\n",
					XMSG_NAME(pXmsg->m_type),pXmsg->m_type);
		if (!TRPT_Action(trnTcidIndex, pXmsg))
		{
			SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Spdu() - action failed failed\r\n");
		}
	}

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Spdu() - return\r\n");
	return 0;
}



/* ======================================================================== */
/* NAME : TRPT_Delete						    							*/
/* 									    									*/
/* DESCRIPTION : Transport State Diagram :SS_DELETE_TC transition received 	*/
/*		- Find the transport connection										*/
/*		- Call the action													*/
/*									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_bd.m_tran_conn contains a SS_DELETE_TC message received from SESS Task */
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*		g_trn_tab_tcid[] updated												*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int TRPT_Delete(xmsg_t* pXmsg)
{
	int trnTcidIndex;	/* trnTcidIndex of g_trn_tab_tcid[] for the current transport connection  	*/

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Delete() - entry\r\n");

	/* Find the transport connection */
	trnTcidIndex = TRPT_GetTcidIndex(pXmsg->m_bd.m_tran_ssdeletetc.m_tcid);
	if (trnTcidIndex < 0)
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Delete() - Unknown tcid %d\r\n", pXmsg->m_bd.m_tran_ssdeletetc.m_tcid);
		/* not found : the event is ignored */

		/* Send IHM_WARNING to IHM Task */
	}
	else
	{
		SM_TRACE_INFO(TRMOD_TRANS, "TRPT_Delete() - %s(0x%02X)\r\n",
					XMSG_NAME(pXmsg->m_type),pXmsg->m_type);

		/* Call the transport state diagram */
		if (!TRPT_Action(trnTcidIndex, pXmsg))
		{
			SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Delete() - action failed failed\r\n");
		}
	}

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Delete() - return\r\n");
	return 0;
}



/* ======================================================================== */
/* NAME : TRPT_Timeout							    						*/
/* 									    									*/
/* DESCRIPTION : Transport State diagram : TIMEOUT received 				*/
/*		- Find the transport connection										*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_timerId contains the Timer Identifier 					  			*/
/*		Task 																*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*			(not used in this function)										*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int TRPT_Timeout(xmsg_t* pXmsg)
{
	int trnTcidIndex;	/* trnTcidIndex of g_trn_tab_tcid[] for the current transport connection  	*/
	unsigned short	timerId;

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Timeout() - entry\r\n");

	timerId = pXmsg->m_bd.m_timer.m_timerId;

	/* Find the transport connection */
	trnTcidIndex = TRPT_GetTcidIndexByTM(timerId);
	if (trnTcidIndex < 0)
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Timeout() - Unknown timerId=0x%02X\r\n", timerId);
		/* not found : the event is ignored */

		/* Send IHM_WARNING to IHM Task */
		return 1;
	}

	SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Timeout() -  timerId=0x%02X, tc trnTcidIndex=%d\r\n", timerId, trnTcidIndex);
	g_trn_tab_tcid[trnTcidIndex].m_timerId = 0;

	/* Call the transport state diagram */
	TRPT_Action(trnTcidIndex, pXmsg);

	/* Release the state diagram instance if the transport connection doesn't exist */
	if (g_trn_tab_tcid[trnTcidIndex].m_state == TRN_IDLE)
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_Timeout() - stat is idle, free trnTcidIndex=%d\r\n", trnTcidIndex);
		TRPT_FreeTcidIndex(trnTcidIndex);
	}

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Timeout() - return\r\n");
	return 0;
}



/* ======================================================================== */
/* NAME : TRPT_TmPoll							    						*/
/* 									    									*/
/* DESCRIPTION : Transport State diagram : TM_POLL received 				*/
/*		- Find the transport connection										*/
/*		- Call the action													*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		pXmsg->m_timerId contains the Timer Identifier 					  			*/
/*		Task 																*/
/*									    									*/
/* OUTPUT PARAMETERS :							    						*/
/*									    									*/
/* RETURN CODE :							    							*/
/*		0 : the calling function must free the memory containing the message*/
/*			(not used in this function)										*/
/*		1 : the calling function do nothing 								*/
/*									   										*/
/* ======================================================================== */
int TRPT_TmPoll(xmsg_t* pXmsg)
{
	int trnTcidIndex;	/* trnTcidIndex of g_trn_tab_tcid[] for the current transport connection  	*/
	unsigned short	timerId;

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_TmPoll() - entry\r\n");

	timerId = pXmsg->m_bd.m_timer.m_timerId;
	/* Find the transport connection */
	trnTcidIndex = TRPT_GetTcidIndexByTMPoll(timerId);
	if (trnTcidIndex < 0)
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_TmPoll() - Unknown pool timerId=0x%02X\r\n", timerId);
		/* not found : the event is ignored */

		/* Send IHM_WARNING to IHM Task */
		return 1;
	}

	SM_TRACE_INFO(TRMOD_TRANS, "TRPT_TmPoll() -  polltimerid=0x%02X, tc trnTcidIndex=%d\r\n", timerId, trnTcidIndex);
	g_trn_tab_tcid[trnTcidIndex].m_pollTimerId = 0;

	/* Call the transport state diagram */
	TRPT_Action(trnTcidIndex, pXmsg);

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_TmPoll() - return\r\n");
	return 0;
}



/* ======================================================================== */
/* NAME : TRPT_AllocTcidIndex					 									*/
/* 									    									*/
/* DESCRIPTION : Get a new entry in g_trn_tab_tcid								*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*		s_tcCount is updated											*/
/*		the transport connection is reserved (g_trn_tab_tcid[].m_tcid)			*/
/*									    									*/
/* RETURN CODE								    							*/
/*		< 0 : no more entry													*/
/*		>=0 : trnTcidIndex in g_trn_tab_tcid											*/
/*									  										*/
/* ======================================================================== */
int TRPT_AllocTcidIndex(void)
{
	int trnTcidIndex;				/* return code : entry found */
	unsigned char newtcid;	/* new tcid to reserve 		 */
	int i;					/* working trnTcidIndex 			 */

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_AllocTcidIndex() - entry\r\n");

	if (s_tcCount >= MAXTCID)
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_AllocTcidIndex() - too many connections=%d\r\n", s_tcCount);
		return -1;						/* too many established connections, no more entry 	*/
	}

	for (trnTcidIndex=0; trnTcidIndex < MAXTCID; trnTcidIndex++)
	{
		if (g_trn_tab_tcid[trnTcidIndex].m_state == TRN_NOT_USED)   /* take the first free entry, reserve it */
		{
			/* Reserve a new tcid */
			for (newtcid=FIRST_VALID_TCID; newtcid < MAXTCID+1; newtcid++)
			{
				for (i=0; i < MAXTCID; i++)
				{
					if ((g_trn_tab_tcid[i].m_state != TRN_NOT_USED) && (g_trn_tab_tcid[i].m_tcid == newtcid))
						break;	/* this tcid already exists, try the next */
				}
				if (i >= MAXTCID)
					break;		/* new tcid found */
			}

			if (newtcid == MAXTCID+1)
			{
				SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_AllocTcidIndex() - no new tcid entry\r\n");
				return -1;		/* new tcid not found */
			}

			g_trn_tab_tcid[trnTcidIndex].m_tcid = newtcid;
			g_trn_tab_tcid[trnTcidIndex].m_state    = TRN_IDLE;
			g_trn_tab_tcid[trnTcidIndex].m_timerId  = 0;
			g_trn_tab_tcid[trnTcidIndex].m_pollTimerId = 0;
			g_trn_tab_tcid[trnTcidIndex].m_len	   = 0;
			g_trn_tab_tcid[trnTcidIndex].m_pbSpdu	   = NULL;
			g_trn_tab_tcid[trnTcidIndex].m_recvSize	   = 0;
			g_trn_tab_tcid[trnTcidIndex].m_pbRcvSpdu   = NULL;
			g_trn_tab_tcid[trnTcidIndex].m_tag      = 0;

			TRPT_ResetFifo(trnTcidIndex);

			s_tcCount++;

			SM_TRACE_INFO(TRMOD_TRANS, "TRPT_AllocTcidIndex() - new entry %d with tcid %d\r\n", trnTcidIndex, newtcid);
			return trnTcidIndex;
		}
	}

	SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_AllocTcidIndex() - no new trnTcidIndex entry\r\n");

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_AllocTcidIndex() - return\r\n");
	return -1;							   			/* no more entry */
}


/* ======================================================================== */
/* NAME : TRPT_FreeTcidIndex					 								*/
/* 									    									*/
/* DESCRIPTION :Delete an entry in g_trn_tab_tcid								*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		trnTcidIndex : trnTcidIndex of the entry to delete								*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*		s_tcCount is updated											*/
/*									    									*/
/* RETURN CODE								    							*/
/*		< 0 : entry not found												*/
/*		>=0 : entry deleted													*/
/*									  										*/
/* ======================================================================== */
int TRPT_FreeTcidIndex(int trnTcidIndex)
{
	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_FreeTcidIndex() - entry, trnTcidIndex=%d\r\n", trnTcidIndex);

    if ((trnTcidIndex < 0) && (trnTcidIndex >= MAXTCID))
	{
		SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_FreeTcidIndex() - invalid trnTcidIndex=%d\r\n", trnTcidIndex);
    	return -1;
	}

	SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_FreeTcidIndex() - delete entry %d with tcid %d\r\n", trnTcidIndex, g_trn_tab_tcid[trnTcidIndex].m_tcid);

	TRPT_Kill_Timer(trnTcidIndex);							/* kill pending TIMEOUT timer */

	if (g_trn_tab_tcid[trnTcidIndex].m_pollTimerId != 0)
	{
		ITC_KillTimer(g_trn_tab_tcid[trnTcidIndex].m_pollTimerId);	/* kill pending TM_POLL timer */
		g_trn_tab_tcid[trnTcidIndex].m_pollTimerId = 0;
	}

	SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_FreeTcidIndex() - free fifo\r\n");
	TRPT_ResetFifo(trnTcidIndex);

	g_trn_tab_tcid[trnTcidIndex].m_state = TRN_NOT_USED;				/* free the entry 		*/

	s_tcCount--;

	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_FreeTcidIndex() - return,s_tcCount=%d\r\n",s_tcCount);
	return trnTcidIndex;
}


/* ======================================================================== */
/* NAME : TRPT_GetTcidIndex					 									*/
/* 									    									*/
/* DESCRIPTION : Get the trnTcidIndex in g_trn_tab_tcid								*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*	tcid :	transport connection (tcid)										*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*		< 0 : tcid not found in g_trn_tab_tcid									*/
/*		>=0 : trnTcidIndex in g_trn_tab_tcid											*/
/*									  										*/
/* ======================================================================== */
int TRPT_GetTcidIndex(unsigned  char tcid)
{
	int trnTcidIndex;		/* return code : entry found */

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_GetTcidIndex() - entry,tcid=%d\r\n", tcid);

	for (trnTcidIndex=0; trnTcidIndex < MAXTCID; trnTcidIndex++)
	{
		if ((g_trn_tab_tcid[trnTcidIndex].m_state != TRN_NOT_USED) && (g_trn_tab_tcid[trnTcidIndex].m_tcid == tcid))
		{
			//SM_TRACE_INFO(TRMOD_TRANS, "TRPT_GetTcidIndex() - tcid=%d found, trnTcidIndex=%d\r\n",
			//			tcid, trnTcidIndex);
			return trnTcidIndex;   /* matching tcid  */
		}
	}

	SM_TRACE_NOTIFY(TRMOD_TRANS, "TRPT_GetTcidIndex() - tcid=%d not found, return -1\r\n", tcid);
	return -1;	   			/* tcid not found */
}


/* ======================================================================== */
/* NAME : TRPT_GetTcidIndexByTM					 								*/
/* 									    									*/
/* DESCRIPTION : Get the trnTcidIndex in g_trn_tab_tcid according to a TIMEOUT timer   */
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*	timerId :	timer identifier											*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*		< 0 : timerId not found in g_trn_tab_tcid								*/
/*		>=0 : trnTcidIndex in g_trn_tab_tcid											*/
/*									  										*/
/* ======================================================================== */
int TRPT_GetTcidIndexByTM(unsigned  short timerId)
{
	int trnTcidIndex;		/* return code : entry found */

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_GetTcidIndexByTM() - entry,timerId=%d\r\n", timerId);

	for (trnTcidIndex=0; trnTcidIndex < MAXTCID; trnTcidIndex++)
	{
		if ((g_trn_tab_tcid[trnTcidIndex].m_state != TRN_NOT_USED) && (g_trn_tab_tcid[trnTcidIndex].m_timerId == timerId))
		{
			SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_GetTcidIndexByTM() - timerId=0x%02X found, trnTcidIndex=%d\r\n",
						timerId, trnTcidIndex);
			return trnTcidIndex;   /* matching timerId  */
		}
	}

	SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_GetTcidIndexByTM() - timerId=0x%02X not found, return -1\r\n", timerId);
	return -1;	   			/* timerId not found */
}


/* ======================================================================== */
/* NAME : TRPT_GetTcidIndexByTMPoll					 							*/
/* 									    									*/
/* DESCRIPTION : Get the trnTcidIndex in g_trn_tab_tcid according to a TM_POLL timer   */
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*	timerId :	timer identifier											*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*		< 0 : timerId not found in g_trn_tab_tcid								*/
/*		>=0 : trnTcidIndex in g_trn_tab_tcid											*/
/*									  										*/
/* ======================================================================== */
int TRPT_GetTcidIndexByTMPoll(unsigned  short timerId)
{
	int trnTcidIndex;		/* return code : entry found */

	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_GetTcidIndexByTMPoll() - entry,timerId=%d\r\n", timerId);

	for (trnTcidIndex=0; trnTcidIndex < MAXTCID; trnTcidIndex++)
	{
		if ((g_trn_tab_tcid[trnTcidIndex].m_state != TRN_NOT_USED) && (g_trn_tab_tcid[trnTcidIndex].m_pollTimerId == timerId))
		{
			//SM_TRACE_INFO(TRMOD_TRANS, "TRPT_GetTcidIndexByTMPoll() - timerId=%d found, trnTcidIndex=%d\r\n",
			//			timerId, trnTcidIndex);
			return trnTcidIndex;   /* matching timerId  */
		}
	}

	SM_TRACE_ERROR(TRMOD_TRANS, "TRPT_GetTcidIndexByTMPoll() - timerId=%d not found, return -1\r\n", timerId);
	return -1;	   			/* timerId not found */
}


/* ======================================================================== */
/* NAME : TRPT_Kill_Timer				 									*/
/* 									    									*/
/* DESCRIPTION : Kill the pending TIMEOUT timer if exists					*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		trnTcidIndex :		instance of the current state diagram					*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*		1 : Success															*/
/*		0 : Error															*/
/*									  										*/
/* ======================================================================== */
void TRPT_Kill_Timer(int trnTcidIndex)
{
	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Kill_Timer() - entry,trnTcidIndex=%d\r\n", trnTcidIndex);
	if (g_trn_tab_tcid[trnTcidIndex].m_timerId != 0)
	{
		SM_TRACE_INFO(TRMOD_TRANS, "TRPT_Kill_Timer() - kill timerId=%d\r\n",
			g_trn_tab_tcid[trnTcidIndex].m_timerId);
		ITC_KillTimer(g_trn_tab_tcid[trnTcidIndex].m_timerId);
		g_trn_tab_tcid[trnTcidIndex].m_timerId = 0;
	}
	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Kill_Timer() - return\r\n");
	return;
}


/* ======================================================================== */
/* NAME : TRPT_Kill_PollTimer				 								*/
/* 									    									*/
/* DESCRIPTION : Kill the pending TIMEPOLL timer if exists					*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		trnTcidIndex :		instance of the current state diagram					*/
/*									 										*/
/* OUTPUT PARAMETERS :							   							*/
/*									    									*/
/* RETURN CODE								    							*/
/*		1 : Success															*/
/*		0 : Error															*/
/*									  										*/
/* ======================================================================== */
void TRPT_Kill_PollTimer(int trnTcidIndex)
{
	SM_TRACE_ENTRY(TRMOD_TRANS, "TRPT_Kill_PollTimer() - entry,trnTcidIndex=%d\r\n",trnTcidIndex);

	if (g_trn_tab_tcid[trnTcidIndex].m_pollTimerId != 0)
	{
		SM_TRACE_INFO(TRMOD_TRANS, "TRPT_Kill_PollTimer() - kill timerId=0x%02X\r\n",
			g_trn_tab_tcid[trnTcidIndex].m_pollTimerId);
		ITC_KillTimer(g_trn_tab_tcid[trnTcidIndex].m_pollTimerId);
		g_trn_tab_tcid[trnTcidIndex].m_pollTimerId = 0;
	}
	SM_TRACE_RETURN(TRMOD_TRANS, "TRPT_Kill_PollTimer() - return\r\n");
	return;
}


